﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RotatingWalkInMatrix
{
    public static class UtilityMoveInMatrix
    {
        public static void ChangeDirection(ref int horizontalStep, ref int verticalStep)
        {
            if (horizontalStep > 1 || horizontalStep < -1 || verticalStep < -1 || verticalStep > 1)
            {
                throw new ArgumentOutOfRangeException("Invalid step value");
            }

            int[] directionsX = { 1, 1, 1, 0, -1, -1, -1, 0 };
            int[] directionsY = { 1, 0, -1, -1, -1, 0, 1, 1 };
            int currentDirectionIndex = 0;

            //Find current direction
            for (int index = 0; index < directionsX.Length; index++)
            {
                if (directionsX[index] == horizontalStep && directionsY[index] == verticalStep)
                {
                    currentDirectionIndex = index;
                    break;
                }

            }

            //Change current direction
            if (currentDirectionIndex == 7)
            {
                horizontalStep = directionsX[0];
                verticalStep = directionsY[0];
                return;
            }
            else
            {
                horizontalStep = directionsX[currentDirectionIndex + 1];
                verticalStep = directionsY[currentDirectionIndex + 1];
            }



        }
        public static bool IsValidDirection(int[,] matrix, int row, int col)
        {
            int[] directionsX = { 1, 1, 1, 0, -1, -1, -1, 0 };
            int[] directionsY = { 1, 0, -1, -1, -1, 0, 1, 1 };
            bool isValedDirection = false;

            //Mark possible directions
            for (int i = 0; i < directionsX.Length; i++)
            {
                if (row + directionsX[i] >= matrix.GetLength(0) || row + directionsX[i] < 0)
                {
                    directionsX[i] = 0;
                }

                if (col + directionsY[i] >= matrix.GetLength(0) || col + directionsY[i] < 0)
                {
                    directionsY[i] = 0;
                }
            }
            //Check for marked field in matrix
            for (int i = 0; i < directionsX.Length; i++)
            {
                if (matrix[row + directionsX[i], col + directionsY[i]] == 0)
                {
                    isValedDirection = true;
                    return isValedDirection;
                }

            }

            return isValedDirection;
        }

        public static void FindEmtyCell(int[,] matrix, out int currentRow, out int currentCol)
        {
            currentRow = -1;
            currentCol = -1;

            //Check for the first posible empty cell(marked with 0), and return -1 if there is no such
            for (int row = 0; row < matrix.GetLength(0); row++)
            {
                for (int col = 0; col < matrix.GetLength(1); col++)
                {
                    if (matrix[row, col] == 0)
                    {
                        currentRow = row;
                        currentCol = col;
                        return;
                    }
                }
            }
        }

        public static void InitializeMatrixWhilePosible(int[,] matrix, ref int number, ref int row, ref int col, ref int horizontalStep, ref int vericalStep)
        {
            int matrixLength = matrix.GetLength(0);
            bool isValidDirection = true;
            while (isValidDirection)
            {
                matrix[row, col] = number;
                isValidDirection = IsValidDirection(matrix, row, col);
                if (isValidDirection)
                {
                    //Check if the next field is marked for empty(with zero), or it is out of the matrix bounds and if not change direction
                    if (row + horizontalStep >= matrixLength || row + horizontalStep < 0 || col + vericalStep >= matrixLength ||
                        col + vericalStep < 0 || matrix[row + horizontalStep, col + vericalStep] != 0)
                    {
                        while ((row + horizontalStep >= matrixLength || row + horizontalStep < 0 || col + vericalStep >= matrixLength ||
                            col + vericalStep < 0 || matrix[row + horizontalStep, col + vericalStep] != 0))
                        {
                            ChangeDirection(ref horizontalStep, ref vericalStep);
                        }
                    }

                    row += horizontalStep;
                    col += vericalStep;
                    number++;
                }
            }
        }

    }
}
